import importlib
import json
from typing import List

from matplotlib.colors import LinearSegmentedColormap, ListedColormap


class SciPalette:
    def __init__(self):
        """
        Cateogorical color palette collection of popular-sci journals.
        """
        handle = importlib.resources.open_binary("gseapy.data", "palette.json")
        self._db = json.load(handle)
        handle.close()

    def __repr__(self):
        # Name that Color. http://chir.ag/projects/name-that-color/
        return str(f"{self.__class__.__name__} color palette collection")

    def name_color(self, hex=None):
        """naming  a color

        :param hex: hex code of color
        """
        return "go to: http://chir.ag/projects/name-that-color/"

    @staticmethod
    def create_colormap(
        colors: List[str] = ["#000080", "#ffffff", "#8b0000"],
        positions: List[float] = [0.0, 0.5, 1.0],
        name: str = "navyblue2darkred",
    ):
        """create colormap given 3 color and break points

        :param colors: a list of color names. Default: ["#000080", "#ffffff", "#8b0000"]
        :param position: position of each color in range [0,1]. Default: [0.0, 0.5, 1.0]
        :param name: name of the return cmap
        :return: matplotlib cmap object
        """
        # cmap = ListedColormap(["#000080", "#ffffff", "#8b0000"])
        # positions = [0.0, 0.5, 1.0]
        if name is None:
            name = "mycmap"
        if colors is None:
            colors = ["#000080", "#ffffff", "#8b0000"]  # navyblue, white, darkred
        if positions is None:
            return LinearSegmentedColormap.from_list(name, colors)
        return LinearSegmentedColormap.from_list(name, list(zip(positions, colors)))

    def npg(self):
        # Discrete Color Palettes
        # Color palette inspired by plots in Nature Reviews Cancer
        return self._db[self.npg.__name__]

    def aaas(self):
        # Color palette inspired by plots in Science from AAAS
        return self._db[self.aaas.__name__]

    def nejm(self):
        # Color palette inspired by plots in The New England Journal of Medicine
        return self._db[self.nejm.__name__]

    def lancet(self):
        # Color palette inspired by plots in Lancet Oncology
        return self._db[self.lancet.__name__]

    def jama(self):
        # Color palette inspired by plots in The Journal of the American Medical Association
        return self._db[self.jama.__name__]

    def jco(self):
        # Color palette inspired by plots in Journal of Clinical Oncology
        return self._db[self.jco.__name__]

    def ucscgb(self):
        # Color palette inspired by UCSC Genome Browser Chromosome Colors
        return self._db[self.ucscgb.__name__]

    def d3js(self, category="c20a"):
        """
        choose category from (c10, c20a, c20b, c20c)
        """
        if category in self._db[self.d3js.__name__]:
            return self._db[self.d3js.__name__][category]

    def igv(self):
        # Color palette inspired by IGV
        return self._db[self.igv.__name__]

    def igv_alternating(self):
        # Color palette inspired by IGV
        return self._db[self.igv_alternating.__name__]

    def locuszoom(self):
        # Color palette inspired by LocusZoom
        return self._db[self.locuszoom.__name__]

    def uchicago(self, category="default"):
        """
        Color palette inspired by University of Chicago Color Palette

        choose category from (light, dark, default)
        """
        if category in self._db[self.uchicago.__name__]:
            return self._db[self.uchicago.__name__][category]

    def hallmark(self, category="dark"):  # hallmark_dark
        """
        choose category from (dark, light)
        """

        if category in self._db[self.hallmark.__name__]:
            return self._db[self.hallmark.__name__][category]

    def cosmic(self):  # signature_substitutions
        # Color palette inspired by COSMIC Hallmarks of Cancer
        return self._db[self.cosmic.__name__]

    def simpsons(self):
        # Color palette inspired by The Simpsons
        return self._db[self.simpsons.__name__]

    def futurama(self):
        # Color palette inspired by Futurama
        return self._db[self.futurama.__name__]

    def rickandmorty(self):
        # Color palette inspired by Rick and Morty
        return self._db[self.rickandmorty.__name__]

    def startrek(self):
        # Color palette inspired by Star Trek
        return self._db[self.startrek.__name__]

    def tron(self):
        # Color palette inspired by Tron Legacy
        return self._db[self.tron.__name__]

    def gsea(self):
        # Color palette inspired by heatmaps generated by GSEA GenePattern
        return self._db[self.gsea.__name__]

    def material(self, category="indigo"):
        """
        choose category from
        (red, pink, purple, deeppurple, blue, lightblue, indigo,
        cyan, teal, lime, green, yellow, amber, organge, deeporange,
        brown, gray, bluegray)
        """
        if category in self._db[self.material.__name__]:
            return self._db[self.material.__name__][category]

    def zeileis(self):
        """
        # https://graphicdesign.stackexchange.com/questions/3682/where-can-i-find-a-large-palette-set-of-contrasting-colors-for-coloring-many-d
        # update 1
        # orig reference http://epub.wu.ac.at/1692/1/document.pdf
        """
        return self._db[self.zeileis.__name__]

    def godsnot(self):
        """
        take from http://godsnotwheregodsnot.blogspot.de/2012/09/color-distribution-methodology.html
        or
        http://godsnotwheregodsnot.blogspot.com/2013/11/kmeans-color-quantization-seeding.html

        """
        return self._db[self.godsnot.__name__]

    def boynton(self):
        return self._db[self.boynton.__name__]

    def kelly(self):
        """
        The set of 22 colours of maximum contrast proposed by Kenneth Kelly in the work:
        http://www.iscc-archive.org/pdf/PC54_1724_001.pdf
        """
        return self._db[self.kelly.__name__]

    def watlington(self):
        return self._db[self.watlington.__name__]

    def glasbey(self):
        return self._db[self.glasbey.__name__]
